Function.RegisterNamespace("Test.System.Script");

[Fixture]
Test.System.Script.ScriptLoader=function(){
    [Fixture]
    function ScriptLoader(){
        [Fact]
        function InitializesStrategyManager(){
            var expected=System.Script.Strategy.StrategyManager;
        
            var actual=System.Script.ScriptLoader.Strategies;
            
            Assert.Type(expected,actual);
        }
    }

    [Fixture]
    function Import(){
        [Fact]
        function ThrowsIfPathIsOmitted(){
            var expected="System.Script.ScriptLoader.Import: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsUndefined(){
            var expected="System.Script.ScriptLoader.Import: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import(undefined);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNull(){
            var expected="System.Script.ScriptLoader.Import: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNotConvertibleToString(){
            var expected="System.Script.ScriptLoader.Import: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function DoesNotThrowIfCallbackIsOmitted(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {
                    Import:function(){}
                };
            }
            
            var actual=Record.Exception(function(){
                target.Import('');
            });
            target.Strategies.Get=targetGet;
            
            Assert.Null(actual);        
        }
        
        [Fact]
        function ThrowsIfCallbackIsUndefined(){
            var expected="System.Script.ScriptLoader.Import: 'callback' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import('',undefined);
            });
            
            Assert.Equal(expected,actual);        
        }

        [Fact]
        function ThrowsIfCallbackIsNull(){
            var expected="System.Script.ScriptLoader.Import: 'callback' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import('',null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfCallbackIsNotAValidFunction(){
            var expected="System.Script.ScriptLoader.Import: 'callback' must be a valid Function pointer.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Import('',new Object());
            });
            
            Assert.Equal(expected,actual);        
        }
        
        [Fact]
        function CallsImportOnStrategy(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {Import:function(){
                    actual=true;
                }};
            }
            var actual=false;
            
            target.Import('');
            target.Strategies.Get=targetGet;
            
            Assert.True(actual);        
        }
        
        [Fact]
        function PassesPathToImportOnStrategy(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {Import:function(path){
                    actual=path;
                }};
            }
            var expected="expected";
            var actual=null;
            
            target.Import(expected);
            target.Strategies.Get=targetGet;
            
            Assert.Equal(expected,actual);        
        }
        
        [Fact]
        function PassesCallbackDelegateToImportOnStrategy(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {Import:function(path,callback){
                    callback();
                }};
            }
            var expected=function(){
                actual=true;
            };
            var actual=false;
            
            target.Import('',expected);
            target.Strategies.Get=targetGet;
            
            Assert.True(actual);        
        }

    }

    [Fixture]
    function Load(){
        [Fact]
        function ThrowsIfSourceIsOmitted(){
            var expected="System.Script.ScriptLoader.Load: 'source' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Load();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfSourceIsUndefined(){
            var expected="System.Script.ScriptLoader.Load: 'source' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Load(undefined);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfSourceIsNull(){
            var expected="System.Script.ScriptLoader.Load: 'source' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Load(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfSourceIsNotConvertibleToString(){
            var expected="System.Script.ScriptLoader.Load: 'source' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.Script.ScriptLoader.Load({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsLoadOnStrategy(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {Load:function(){
                    actual=true;
                }};
            }
            var actual=false;
            
            target.Load('');
            target.Strategies.Get=targetGet;
            
            Assert.True(actual);        
        }
        
        [Fact]
        function PassesSourceToLoadOnStrategy(){
            var target=System.Script.ScriptLoader;
            var targetGet=target.Strategies.Get;
            target.Strategies.Get=function(){
                return {Load:function(source){
                    actual=source;
                }};
            }
            var expected="expected";
            var actual=null;
            
            target.Load(expected);
            target.Strategies.Get=targetGet;
            
            Assert.Equal(expected,actual);        
        }
        
    }
}